// 导入React相关依赖
import React, { useRef, useState, useEffect } from 'react';
// 导入React Three Fiber的核心组件和Hooks
import { Canvas, extend, useThree, useLoader, useFrame } from '@react-three/fiber';
// 导入GLTF模型加载器，用于加载3D模型文件
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
// 导入轨道控制器，用于鼠标控制3D场景
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 导入动作类型定义
import type { ActionType } from './ActionController';

// 扩展Three.js，让React Three Fiber能够识别OrbitControls组件
extend({ OrbitControls });

// 轨道控制组件 - 负责处理鼠标交互（旋转、缩放、平移）
const Orbit = () => {
  // 从useThree Hook获取相机和渲染器对象
  const { camera, gl } = useThree();
  // 返回轨道控制器，传入相机和渲染器的DOM元素
  return <orbitControls args={[camera, gl.domElement]} />;
};

// 旋转模型组件 - 负责3D模型的显示和动作动画
const RotatingModel = ({ model, action }: { model: any; action: ActionType }) => {
  // 创建ref引用，用于直接操作3D对象
  const meshRef = useRef<any>();
  // 动画状态管理
  const [animationState, setAnimationState] = useState({
    rotationY: 0, // Y轴旋转角度
    waveOffset: 0, // 挥手动作偏移
    spinSpeed: 0, // 转圈速度
    isWaving: false, // 是否正在挥手
    isSpinning: false, // 是否正在转圈
  });

  // 使用useFrame Hook创建动画循环，每帧都会执行
  useFrame((state, delta) => {
    // 检查mesh对象是否存在
    if (meshRef.current) {
      // 根据动作类型执行不同的动画
      switch (action) {
        case 'bow':
          // 鞠躬动作 - 模拟鞠躬时的身体前倾
          setAnimationState(prev => ({
            ...prev,
            isWaving: false,
            isSpinning: false,
          }));
          // 鞠躬 - 身体前倾，模拟鞠躬动作
          meshRef.current.rotation.x = Math.sin(state.clock.elapsedTime * 1.6) * 0.45;
          // 鞠躬时的轻微上下移动，模拟鞠躬时的身体动作
          meshRef.current.position.y = -0.3 + Math.sin(state.clock.elapsedTime * 1.6) * 0.08;
          // 鞠躬时的轻微左右摆动，模拟鞠躬时的身体姿态
          meshRef.current.rotation.z = Math.sin(state.clock.elapsedTime * 1.2) * 0.03;
          break;
          
        case 'spin':
          // 转圈动作 - 快速旋转
          setAnimationState(prev => ({
            ...prev,
            isWaving: false,
            isSpinning: true,
            rotationY: prev.rotationY + delta * 2, // 快速旋转
          }));
          meshRef.current.rotation.y = animationState.rotationY;
          break;
          
        case 'jump':
          // 跳跃动作 - 上下跳跃
          setAnimationState(prev => ({
            ...prev,
            isWaving: false,
            isSpinning: false,
          }));
          // 跳跃效果 - 使用正弦波模拟跳跃的上下运动
          const jumpHeight = Math.abs(Math.sin(state.clock.elapsedTime * 3)) * 0.3;
          meshRef.current.position.y = -0.3 + jumpHeight;
          // 跳跃时轻微的前后倾斜，模拟跳跃时的身体姿态
          meshRef.current.rotation.x = Math.sin(state.clock.elapsedTime * 6) * 0.05;
          break;
          
        case 'idle':
        default:
          // 待机状态 - 缓慢呼吸效果
          setAnimationState(prev => ({
            ...prev,
            isWaving: false,
            isSpinning: false,
          }));
          meshRef.current.rotation.y += delta * 0.3; // 缓慢旋转
          meshRef.current.position.y = -0.3 + Math.sin(state.clock.elapsedTime * 0.5) * 0.05; // 轻微上下移动
          break;
      }
    }
  });

  return (
    // 3D网格对象，包含模型和光照
    <mesh ref={meshRef} position={[0, -0.3, 0]}>
      {/* 半球光 - 模拟天空光照，从上方照射 */}
      <hemisphereLight intensity={0.8} groundColor="white" />
      {/* 环境光 - 提供整体照明，避免完全黑暗的区域 */}
      <ambientLight intensity={0.6} />
      {/* 定向光 - 模拟太阳光，从指定方向照射 */}
      <directionalLight position={[5, 5, 5]} intensity={0.8} />
      {/* 原始3D模型 - 直接渲染GLTF模型场景 */}
      <primitive object={model.scene} scale={1.2} />
    </mesh>
  );
};

// 主组件 - 负责加载3D模型并设置3D场景
const MySelf: React.FC<{ action: ActionType }> = ({ action }) => {
  // 使用useLoader Hook加载GLB模型文件
  // GLTFLoader是加载器，"/digital-human.glb"是模型文件路径
  const model = useLoader(GLTFLoader, "/digital-human.glb");

  return (
    // 外层容器，设置100%宽高和相对定位
    <div style={{ height: "100%", width: "100%", position: "relative" }}>
      {/* 3D画布组件 - 这是Three.js的渲染容器 */}
      <Canvas
        style={{ backgroundColor: "transparent" }} // 设置透明背景
        camera={{ position: [0, -0.5, 4], fov: 60 }} // 设置相机位置和视野角度
      >
        {/* 轨道控制器 - 允许用户用鼠标控制视角 */}
        <Orbit />
        {/* 旋转模型组件 - 传入加载的模型数据和动作类型 */}
        <RotatingModel model={model} action={action} />
      </Canvas>
    </div>
  );
};

// 导出组件供其他文件使用
export default MySelf;
